#include"common.hpp"
#include <boost/filesystem.hpp>
#include"Tool.hpp"

const std::string file_path = "./data/html";

struct Docinfo{
    std::string _title;
    std::string _content;
    std::string _url;
};

bool InputFilePath(const std::string& path,std::vector<std::string>* list);
bool ParseHtml(const std::vector<std::string>& filelist, std::vector<Docinfo> *result);
bool SaveHtml(const std::vector<Docinfo>& result);

//main
int main()
{
    //list
    std::vector<std::string> filename_list;     
    if(!InputFilePath(file_path,&filename_list)){
        std::cout<<"err Path can't input"<<std::endl;
        return 1;
    }

    //result
    std::vector<Docinfo> result;
    if(!ParseHtml(filename_list,&result)){
        std::cout<<"err ParseHtml"<<std::endl;
        return 2;
    }
    
    if(!SaveHtml(result)){
        std::cout<<"err SaveHtml"<<std::endl;
        return 3;
    }
    return 0;   
}

bool InputFilePath(const std::string& path,std::vector<std::string>* list){
    namespace fs = boost::filesystem;
    fs::path root_path(path);
    if(!fs::exists(root_path)) {
        std::cerr<<"file no exists"<<std::endl;
        return false;
    }

    fs::recursive_directory_iterator end;
    for(fs::recursive_directory_iterator iter(path); iter != end; iter++){
        if(!fs::is_regular_file(*iter)) continue;
        if(iter->path().extension() != ".html") continue;

        std::string filepath = iter->path().string();
        list->emplace_back(std::move(filepath));
    }

    return true;
}



//<title>What's Included in This Document</title>
bool Parsertitle(const std::string& filecontent,Docinfo* doc){

    std::size_t start = filecontent.find("<title>");
    if(start == std::string::npos)return false;
    std::size_t end = filecontent.find("</title>");
    if(end == std::string::npos)return  false;

    start += std::string("<title>").size();
    std::string title = filecontent.substr(start,end - start);
    doc->_title = title;
    return true;
}

bool Parsercontent(const std::string& filecontent,Docinfo* doc){
    //不如状态机 并且有bug
    // std::stringstream ss(filecontent);
    // std::string line;

    // while(std::getline(ss,line)){
    //     std::size_t pos = 0;
    //     while(true){
    //         std::size_t start = line.find('>',pos);
    //         if(start == std::string::npos) break;
    //         std::size_t end = line.find('<',start);  
    //         if(end == std::string::npos) break;
    //         pos = end;
    //         if(start >= end)continue; 
    //         doc->_content += line.substr(start+1,end-start-1) + " ";
    //     }
    // }
    //verson-2
    // enum status{
    //     LABEL,
    //     CONTENT
    // };
    // enum status s = LABEL;
    // for(char c : filecontent){
    //     switch (s)
    //     {
    //     case LABEL:
    //         if(c == '>')
    //             s = CONTENT;
    //         break;
    //     case CONTENT:
    //         if(c == '<') s = LABEL;
    //         else{
    //             if(c == '\n') c = ' ';
    //             doc->_content.push_back(c);
    //         }
    //     default:
    //         break;
    //     }
    // }
    enum status {
        LABEL,
        CONTENT
    };

    enum status s = LABEL;
    bool need_space = false; // 标记是否需要添加空格

    for(char c : filecontent) {
        switch (s) {
            case LABEL:
                if(c == '>') {
                    s = CONTENT;
                }
                break;
            case CONTENT:
                if(c == '<') {
                    s = LABEL;
                } else if (std::isspace(static_cast<unsigned char>(c))) {
                    // 遇到任何空白字符，标记需要空格
                    need_space = true;
                } else {
                    // 在非空白字符前添加空格（如果需要）
                    if(need_space && !doc->_content.empty()) {
                        doc->_content.push_back(' ');
                        need_space = false;
                    }
                    doc->_content.push_back(c);
                }
                break;
            default:
                break;
        }
    }
    return true;
}

bool Parserurl(const std::string& filepath,Docinfo* doc){
    size_t start = filepath.rfind('/');
    std::string filename = filepath.substr(start);
    doc->_url = "./html"+ filename;
    return true;
}

bool ParseHtml(const std::vector<std::string>& filelist, std::vector<Docinfo> *result){
    for(auto& file : filelist){
        std::string Onehtml;
        if(!Tool::ReadHtml::Readfile(file,&Onehtml)){
            std::cerr<<"Readfile false"<<std::endl;
            return false;
        }
        Docinfo doc;
        //title
        if(!Parsertitle(Onehtml,&doc)){
            std::cerr<<"Parsertitle false"<<std::endl;
            return false;
        }
        //content
        if(!Parsercontent(Onehtml,&doc)){
            std::cerr<<"Parsercontent false"<<std::endl;
            return false;
        }
        //url
        if(!Parserurl(file,&doc)){
            std::cerr<<"Parserurl false"<<std::endl;
            return false;
        }
        // std::cout<<"parser end" <<std::endl;
        result->emplace_back(std::move(doc));
    }
    return true;
}

bool SaveHtml(const std::vector<Docinfo>& result){
#define SEP '\3'
    std::ofstream ofs(source,std::ios::out);
    if(!ofs.is_open()){
        std::cerr << "open rource false"<<std::endl;
        return false;
    }
    for(auto& onehtml :result){
        std::string tmp;
        tmp += onehtml._title + SEP;
        tmp += onehtml._content + SEP;
        tmp += onehtml._url + "\n";
        ofs.write(tmp.c_str(),tmp.size());
    }
    ofs.close();
    return true;
}
